package android.magical;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

public class MagiCalBT extends Activity {
	
	
	private String TAG = "MagicalBT";
	private AcceptThread acceptThread;
	private ConnectThread connectThread;
	private ConnectedThread connectedThread;
	public static final int POST_MESSAGE = 0;
	// unique application UUID
	private static final UUID appuuid = UUID
			.fromString("f5c58520-87f7-11e1-b0c4-0800200c9a66");// the app ID,
																// app need to
																// have a common
																// UUID to
																// communicate

	// unique application name for bluetooth communication
	private static final String name = "MagiCalBT";
	private final Handler handle;
	private BluetoothAdapter BTAdapter;
	private BluetoothAdapter BTAdapterCopy;
	private IntentFilter intent = new IntentFilter();
	private boolean startBT=true;

	public MagiCalBT(Handler mHandler) {
		
		handle = mHandler;

	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);

		intent.addAction(BluetoothDevice.ACTION_FOUND);

		// Register action ACTION_FOUND, so that we can execute
		// some code each time the intent found a bluetooth device
		intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
		
		// Below are other action available
		/*
		 * intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
		 * intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
		 * intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
		 */

		// Register intent so that BroadcastReceiver will be called
		// when it matches intent filters
		//registerReceiver(DeviceBonding, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));



	}

	public void start(BluetoothDevice device) {

	

		
		connectThread = new ConnectThread(device);
		connectThread.start();
	}

	public void accept(BluetoothAdapter bluetooth) {
		if (startBT==true){
			BTAdapterCopy=bluetooth;
			startBT=false;
		}
		BTAdapter=BTAdapterCopy;
		acceptThread =new AcceptThread(BTAdapter);
		acceptThread.start();
	}

	public void connected(String message) {

		byte[] send = message.getBytes();
		ConnectedThread ct;
		// Synchronize a copy of the ConnectedThread
		synchronized (this) {
			ct = connectedThread;
		}
		// Perform the write unsynchronized
		ct.write(send);
	}

	// The device will accept connection once Bluetooth and discoverability is
	// on
	private class AcceptThread extends Thread {

		private final BluetoothServerSocket bTServerSocket;

		public AcceptThread(BluetoothAdapter bluetooth) {

			BluetoothServerSocket tempsocket = null; // temporary socket as
														// btServerSocket is a
														// final
			try {
				tempsocket = bluetooth.listenUsingRfcommWithServiceRecord(name,
						appuuid); // only accept application with the same
									// application name and app UUID
			} catch (IOException e) {
			}
			bTServerSocket = tempsocket;
		}

		public void run() {// when some devices attempt to connect with us
			BluetoothSocket socket = null;
			while (true) {
				try {
					socket = bTServerSocket.accept(); // accept socket
				} catch (IOException e) {
					break;
				}

				if (socket != null) {
					connectedThread = new ConnectedThread(socket);// it will
																	// pass the
																	// socket on
																	// to
																	// connected
																	// thread
					Log.i(TAG,"Device: "+socket.getRemoteDevice()+" is connecting to me....");
					connectedThread.start(); // and start the connected thread
					try {
						bTServerSocket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
					break;
				}
			}
		}

	}

	// establish connection when user click on a device on the device list
	private class ConnectThread extends Thread {

		private final BluetoothSocket bTSocket;

		public ConnectThread(BluetoothDevice device) {

			Log.i(TAG, "ConnectThread");
			BluetoothSocket tmp = null;

			try {
				
				tmp = device.createRfcommSocketToServiceRecord(appuuid); // connection
																			// need
																			// to
																			// match
																			// the
																			// same
																			// application
																			// UUID
																			// in
																			// order
																			// for
																			// a
																			// connection
																			// to
																			// be
																			// established
			} catch (IOException e) {
			}
			bTSocket = tmp;
		}

		public void run() {// once the application are able to connect to the
							// other device

			try {
				bTSocket.connect();
				
			} catch (IOException connectException) {
				try {
					bTSocket.close();
				} catch (IOException closeException) {
				}
				return;
			}
			Log.i(TAG,"connect");
			connectedThread = new ConnectedThread(bTSocket);
			connectedThread.start();
			connected(ViewEventFragment.getMessage());
		}

	}

	private class ConnectedThread extends Thread {

		private final InputStream bTInStream;
		private final OutputStream btTOutStream;
		private final BluetoothSocket bTSocket;

		public ConnectedThread(BluetoothSocket socket) {
			bTSocket = socket;
			InputStream tempIn = null;
			OutputStream tempOut = null;
			// get the bTSocket input and output stream
			try {
				tempIn = socket.getInputStream();
				tempOut = socket.getOutputStream();
			} catch (IOException e) {
			}

			bTInStream = tempIn;
			btTOutStream = tempOut;
		}

		public void run() {

			byte[] buffer = new byte[1024];
			int bytes;

			// handle any input stream
			while (true) {
				try {

					bytes = bTInStream.read(buffer);

					// send buffer data back to UI using handler
					handle.obtainMessage(POST_MESSAGE, bytes, -1,
							buffer).sendToTarget();
/*					DatabaseControl test = new DatabaseControl(getApplicationContext()).open();
					test.addItem("stranger", "3/5/2012", "15:00", "message");
					test.close();*/

					bTSocket.close();
					accept(BTAdapterCopy);
				} catch (IOException e) {
					break;
				}
			}
		}

		public void write(byte[] bytes) {// handle any output stream, when user
											// click "send" button on UI
			try {

				btTOutStream.write(bytes);
				btTOutStream.flush();
				
			} catch (IOException e) {
			}
		}

	}
	

}
